﻿using Furion.DatabaseAccessor;
using Furion.DatabaseAccessor.Extensions;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using Admin.NET.Core;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Linq.Dynamic.Core;
using Microsoft.AspNetCore.Http;
using System.Text;
using System.Web;
using System.ComponentModel;
using System.Data;
namespace Admin.NET.Application
{
    /// <summary>
    /// 学生3(测试NULL值)服务
    /// </summary>
    [ApiDescriptionSettings("TestDemo", Name = "TestStudent3", Order = 100)]
    [Route("api")]
    public class TestStudent3Service : ITestStudent3Service, IDynamicApiController, ITransient
    {
        private readonly IRepository<TestStudent3,MasterDbContextLocator> _testStudent3Rep;
        private readonly IRepository<SysDictType, MasterDbContextLocator> _sysDictTypeRep;
        private readonly IRepository<SysDictData, MasterDbContextLocator> _sysDictDataRep;
        private readonly ISysExcelTemplateService _sysExcelTemplateService;
        private readonly static object _lock = new();

        public TestStudent3Service(
            IRepository<TestStudent3,MasterDbContextLocator> testStudent3Rep
            ,IRepository<SysDictType, MasterDbContextLocator> sysDictTypeRep
            ,IRepository<SysDictData, MasterDbContextLocator> sysDictDataRep
            ,ISysExcelTemplateService sysExcelTemplateService
        )
        {
            _testStudent3Rep = testStudent3Rep;
         _sysDictTypeRep = sysDictTypeRep;
         _sysDictDataRep = sysDictDataRep;
         _sysExcelTemplateService = sysExcelTemplateService;
        }

        /// <summary>
        /// 分页查询学生3(测试NULL值)
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpGet("TestStudent3/page")]
        public async Task<PageResult<TestStudent3Output>> Page([FromQuery] TestStudent3Search input)
        {
            var testStudent3s = await _testStudent3Rep.DetachedEntities
                                     .Where(!string.IsNullOrEmpty(input.Name), u => u.Name == input.Name)
                                     .Where(input.Age != null, u => u.Age == input.Age)
                                     .Where(input.HasMoney != null, u => u.HasMoney == input.HasMoney)
                                     .Where(input.StartName != null, u => u.StartName == input.StartName)
                                     .Where(input.Gender != null, u => u.Gender == input.Gender)
                                     .Where(input.BrithDate!=null, u => u.BrithDate>=  Convert.ToDateTime(input.BrithDate[0]) && u.BrithDate<= Convert.ToDateTime(input.BrithDate[1]))
                                     .Where(input.CreatedTime!=null, u => u.CreatedTime>=  Convert.ToDateTime(input.CreatedTime[0]) && u.CreatedTime<= Convert.ToDateTime(input.CreatedTime[1]))
                                     .Where(input.UpdatedTime!=null, u => u.UpdatedTime>=  Convert.ToDateTime(input.UpdatedTime[0]) && u.UpdatedTime<= Convert.ToDateTime(input.UpdatedTime[1]))
                                     .Where(!string.IsNullOrEmpty(input.CreatedUserName), u => u.CreatedUserName == input.CreatedUserName)
                                     .Where(!string.IsNullOrEmpty(input.UpdatedUserName), u => u.UpdatedUserName == input.UpdatedUserName)
                                     .OrderBy(PageInputOrder.OrderBuilder<TestStudent3Search>(input))
                                     .ProjectToType<TestStudent3Output>()
                                     .ToADPagedListAsync(input.PageNo, input.PageSize);
            return testStudent3s;
        }

        /// <summary>
        /// 不分页查询学生3(测试NULL值)列表
        /// </summary>
        /// <param name="input">学生3(测试NULL值)查询参数</param>
        /// <returns>(学生3(测试NULL值))实例列表</returns>
        [HttpGet("TestStudent3/listNonPage")]
        public async Task<List<TestStudent3Output>> ListNonPageAsync([FromQuery] TestStudent3SearchNonPage input)
        {
            var pName = input.Name?.Trim() ?? "";
            var pAge = input.Age;
            var pHasMoney = input.HasMoney;
            var pStartName = input.StartName;
            var pGender = input.Gender;
            var pBrithDate = input.BrithDate;
            var pCreatedTime = input.CreatedTime;
            var pUpdatedTime = input.UpdatedTime;
            var pCreatedUserName = input.CreatedUserName?.Trim() ?? "";
            var pUpdatedUserName = input.UpdatedUserName?.Trim() ?? "";
            var testStudent3s = await _testStudent3Rep.DetachedEntities
                .Where(!string.IsNullOrEmpty(pName), u => u.Name == pName)
                .Where(pAge != null, u => u.Age == pAge)
                .Where(pHasMoney != null, u => u.HasMoney == pHasMoney)
                .Where(pStartName != null, u => u.StartName == pStartName)
                .Where(pGender != null, u => u.Gender == pGender)
           .Where(input.BrithDate!=null, u => u.BrithDate>=  Convert.ToDateTime(input.BrithDate[0]) && u.BrithDate<= Convert.ToDateTime(input.BrithDate[1]))
           .Where(input.CreatedTime!=null, u => u.CreatedTime>=  Convert.ToDateTime(input.CreatedTime[0]) && u.CreatedTime<= Convert.ToDateTime(input.CreatedTime[1]))
           .Where(input.UpdatedTime!=null, u => u.UpdatedTime>=  Convert.ToDateTime(input.UpdatedTime[0]) && u.UpdatedTime<= Convert.ToDateTime(input.UpdatedTime[1]))
                .Where(!string.IsNullOrEmpty(pCreatedUserName), u => u.CreatedUserName == pCreatedUserName)
                .Where(!string.IsNullOrEmpty(pUpdatedUserName), u => u.UpdatedUserName == pUpdatedUserName)
            .OrderBy(PageInputOrder.OrderNonPageBuilder(input))
            .ProjectToType<TestStudent3Output>()
            .ToListAsync();
            return testStudent3s;
        }

         /// <summary>
        /// 获取单个学生3(测试NULL值)
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpGet("TestStudent3/detail")]
        public async Task<TestStudent3Output> Get([FromQuery] QueryeTestStudent3Input input)
        {
           return (await _testStudent3Rep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == input.Id)).Adapt<TestStudent3Output>();
        }

        /// <summary>
        /// 获取学生3(测试NULL值)列表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpGet("TestStudent3/list")]
        public async Task<List<TestStudent3Output>> List([FromQuery] TestStudent3Input input)
        {
            return await _testStudent3Rep.DetachedEntities.ProjectToType<TestStudent3Output>().ToListAsync();
        }    

        #region 增、删、改

        /// <summary>
        /// 增加学生3(测试NULL值)
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("TestStudent3/add")]
        public async Task Add(AddTestStudent3Input input)
        {
            var testStudent3 = input.Adapt<TestStudent3>();
                        //验证
            await CheckExisit(testStudent3);

            testStudent3.CreatedUserId = testStudent3.UpdatedUserId = SysHelper.GetUserId();
            testStudent3.CreatedUserName = testStudent3.UpdatedUserName = SysHelper.GetUserName();
            testStudent3.CreatedTime = testStudent3.UpdatedTime = SysHelper.GetNowTime();
            await _testStudent3Rep.InsertAsync(testStudent3);
        }

        /// <summary>
        /// 删除学生3(测试NULL值)
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("TestStudent3/delete")]
        public async Task Delete(DeleteTestStudent3Input input)
        {
            var testStudent3 = await _testStudent3Rep.FirstOrDefaultAsync(u => u.Id == input.Id);
            await _testStudent3Rep.DeleteAsync(testStudent3);
            
        }

        /// <summary>
        /// 更新学生3(测试NULL值)
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("TestStudent3/edit")]
        public async Task Update(UpdateTestStudent3Input input)
        {
            var isExist = await _testStudent3Rep.AnyAsync(u => u.Id == input.Id, false);
            if (!isExist) throw Oops.Oh(ErrorCode.D1002);

            var testStudent3 = input.Adapt<TestStudent3>();
            //验证
            await CheckExisit(testStudent3,true);

            testStudent3.UpdatedUserId = SysHelper.GetUserId();
            testStudent3.UpdatedUserName = SysHelper.GetUserName();
            testStudent3.UpdatedTime = SysHelper.GetNowTime();
            await _testStudent3Rep.UpdateAsync(testStudent3,ignoreNullValues:true);
        }

        #endregion

        #region 导入

        /// <summary>
        /// Excel模板导入学生3(测试NULL值)功能
        /// </summary>
        /// <param name="file">Excel模板文件</param>
        /// <returns>导入的记录数</returns>
        [HttpPost("TestStudent3/importExcel")]
        public async Task<int> ImportExcelAsync(IFormFile file)
        { 
            int _HeadStartLine = 2;//第1行是说明,第2行是列名
            int _DataStartLine = 3;//第3行开始是数据

            DataTable importDataTable = ExcelUtil.ImportExcelToDataTable(file, _HeadStartLine, _DataStartLine);
            var addList =await CommonImport(importDataTable, _DataStartLine);

            lock (_lock)
            {
                _testStudent3Rep.InsertAsync(addList);
               
            }
            await Task.CompletedTask;
            return addList.Count;
        }

        /// <summary>
        ///  DataTable转换实体对象列表
        /// </summary>
        /// <param name="dataTable"></param>
        /// <param name="dataStartLine">模版列名开始行</param>
        /// <returns></returns>
        private async Task<List<TestStudent3>> CommonImport(DataTable dataTable, int dataStartLine)
        {

            var details = new List<TestStudent3>();
            int index = dataStartLine;//模版列名开始行
            foreach (System.Data.DataRow row in dataTable.Rows)
            {
                index++;

               //导入模版定制化代码（替换模版使用）
                                          
                           var addItem = new TestStudent3()
                            {
                               CreatedTime = SysHelper.GetNowTime(),
                               CreatedUserId = SysHelper.GetUserId(),
                               CreatedUserName = SysHelper.GetUserName(),
                               UpdatedTime = SysHelper.GetNowTime(),
                               UpdatedUserId = SysHelper.GetUserId(),
                               UpdatedUserName = SysHelper.GetUserName()
                             };
                          #region 定义变量
                           var _Name = "";//学生姓名
                           var _Age = "";//学生年龄
                           var _HasMoney = "";//零花钱
                           var _StartName = "";//是否在校
                           var _Gender = "";//性别
                           var _BrithDate = "";//出生日期
                           var _CreatedTime = "";//创建时间
                           var _UpdatedTime = "";//更新时间
                           var _CreatedUserName = "";//创建者名称
                           var _UpdatedUserName = "";//修改者名称
                          #endregion
                          
                          
                          #region 取值
                           _Name = row["学生姓名"]?.ToString() ;
                           _Age = row["学生年龄"]?.ToString() ;
                           _HasMoney = row["零花钱"]?.ToString() ;
                           _StartName = row["是否在校"]?.ToString() ;
                           _Gender = row["性别"]?.ToString() ;
                           _BrithDate = row["出生日期"]?.ToString() ;
                           _CreatedTime = row["创建时间"]?.ToString() ;
                           _UpdatedTime = row["更新时间"]?.ToString() ;
                           _CreatedUserName = row["创建者名称"]?.ToString() ;
                           _UpdatedUserName = row["修改者名称"]?.ToString() ;
                          #endregion
                          
                          
                          #region 验证
                          
                          if (string.IsNullOrEmpty(_Name))
                          {
                            throw Oops.Oh($"第{index}行[学生姓名]{_Name}不能为空！");
                          }
                          
                          if(!string.IsNullOrEmpty(_Name))
                          {
                                addItem.Name = (string)_Name;
                           }
                          if(!string.IsNullOrEmpty(_Age))
                          {
                              if (!int.TryParse(_Age, out int outAge)&&!string.IsNullOrEmpty(_Age))
                              {
                                 throw Oops.Oh($"第{index}行[学生年龄]{_Age}值不正确！");
                              }
                              if (outAge <= 0&&!string.IsNullOrEmpty(_Age))
                              {
                                 throw Oops.Oh($"第{index}行[学生年龄]{_Age}值不能小于等于0！");
                              }
                              else
                              {
                                 addItem.Age = outAge;
                              }
                          
                          }
                          if(!string.IsNullOrEmpty(_HasMoney))
                          {
                              if (!decimal.TryParse(_HasMoney, out decimal outHasMoney)&&!string.IsNullOrEmpty(_HasMoney))
                              {
                                 throw Oops.Oh($"第{index}行[零花钱]{_HasMoney}值不正确！");
                              }
                              if (outHasMoney <= 0&&!string.IsNullOrEmpty(_HasMoney))
                              {
                                 throw Oops.Oh($"第{index}行[零花钱]{_HasMoney}值不能小于等于0！");
                              }
                              else
                              {
                                 addItem.HasMoney = outHasMoney;
                              }
                          
                          }
                          if(!string.IsNullOrEmpty(_StartName))
                          {
                            if(!_StartName.Equals("是") && !_StartName.Equals("否"))
                             {
                               throw Oops.Oh($"第{index}行[是否在校]{_StartName}值不正确！");
                             }
                             else
                             {
                               bool outStartName = _StartName.Equals("是") ? true : false;
                               addItem.StartName = outStartName;
                             }
                             }
                          
                          if(!string.IsNullOrEmpty(_Gender))
                          {
                          Admin.NET.Core.GenderChinese  enumGender = default(Admin.NET.Core.GenderChinese);
                          
                             if(!Enum.TryParse<Admin.NET.Core.GenderChinese>(_Gender, out enumGender)&&!string.IsNullOrEmpty(_Gender))
                              {
                                throw Oops.Oh($"第{index}行[性别]{_Gender}值不正确！");
                              }
                              else
                              {
                                 addItem.Gender = enumGender;
                              }
                          
                           }
                          if(!string.IsNullOrEmpty(_BrithDate))
                          {
                                addItem.BrithDate =   Convert.ToDateTime(_BrithDate);
                           }
                          if(!string.IsNullOrEmpty(_CreatedTime))
                          {
                                addItem.CreatedTime =   Convert.ToDateTime(_CreatedTime);
                           }
                          if(!string.IsNullOrEmpty(_UpdatedTime))
                          {
                                addItem.UpdatedTime =   Convert.ToDateTime(_UpdatedTime);
                           }
                          if(!string.IsNullOrEmpty(_CreatedUserName))
                          {
                                addItem.CreatedUserName = (string)_CreatedUserName;
                           }
                          if(!string.IsNullOrEmpty(_UpdatedUserName))
                          {
                                addItem.UpdatedUserName = (string)_UpdatedUserName;
                           }
                          #endregion
                          

              
                details.Add(addItem);
            }
              //验重
              await CheckExisitForImport(details);
            
            return details;
        }

        /// <summary>
        /// 根据版本下载学生3(测试NULL值)的Excel导入模板
        /// </summary>
        /// <param name="version">模板版本</param>
        /// <returns>下载的模板文件</returns>
        [HttpGet("TestStudent3/downloadExcelTemplate")]
        public IActionResult DownloadExcelTemplate([FromQuery] string version)
        {
            string _path = TemplateConst.EXCEL_TEMPLATEFILE_导入模版路径 + $"\\TestStudent3{TemplateConst.EXCEL_TEMPLATEFILE_导入模版名称后缀}.xlsx";
            var fileName = HttpUtility.UrlEncode($"导入模板(学生3(测试NULL值)).xlsx", Encoding.GetEncoding("UTF-8"));
            return new FileStreamResult(new FileStream(_path, FileMode.Open), "application/octet-stream") { FileDownloadName = fileName };
        }

        #endregion

        #region 私有方法

        /// <summary>
        /// 根据联合主键验证数据是否已存在-数据库
        /// </summary>
        /// <param name="input"></param>
        /// <param name="isEdit"></param>
        /// <returns></returns>
        private async Task CheckExisit( TestStudent3 input,bool isEdit=false)
        {
           

           
           bool isExist = false;
           if (!isEdit)//新增
           {
                   //数据是否存在重复
                   isExist = await _testStudent3Rep.AnyAsync(u =>
                                   u.Name.Equals(input.Name)
                   ,false);
          }
           else//编辑 
          {

          
                
                 //当前编辑数据以外是否存在重复
                  isExist = await _testStudent3Rep.AnyAsync(u => 
                                    u.Id != input.Id
                                    &&u.Name.Equals(input.Name)
                    ,false);
               }
               
        

            if (isExist) throw Oops.Oh(ErrorCode.E0001);
       }
        
        /// <summary>
        /// 根据联合主键验证数据是否已存在-导入时验证
        /// </summary>
        /// <param name="inputs"></param>
        /// <returns></returns>
        private async Task CheckExisitForImport(List<TestStudent3> inputs)
        { 
            //根据联合主键验证表格中中是否已存在相同数据  
                 if (inputs?.Count <= 0)
                 {
                     throw Oops.Oh($"导入数据不能为空");
                 }
                 //数据是否重复
                 var existExcelItem = inputs.GroupBy(g => new {
                                               g.Name
                                               })
                                               .Where(g => g.Count() > 1)
                                               .Select(s => new {
                                               s.Key.Name
                                               }).FirstOrDefault();
                 if (existExcelItem != null)
                 {
                   var item= existExcelItem.Adapt<TestStudent3>();
                   throw Oops.Oh($"导入的表格中,学生姓名[{item.Name}]已存在");
                 }
                      



    //根据联合主键验证数据库中是否已存在相同数据
                 var existDBItem = await _testStudent3Rep.DetachedEntities.FirstOrDefaultAsync(w=> 
                                                                         inputs.Select(s=>""
                                                                           +s.Name
                                                                        )
                                                                        .Contains(""
                                                                         +w.Name
                  ));
                  if (existDBItem != null)
                 {
                   var item= existDBItem.Adapt<TestStudent3>();
                   throw Oops.Oh($"系统中,学生姓名[{item.Name}]已存在");
                 }
        }

        #endregion
    }
}
